1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 import sun.misc.DoubleConsts;
32 import sun.misc.FpUtils;
33
34 public class HypotTests {
35 private HypotTests(){}
36
37 static final double infinityD = Double.POSITIVE_INFINITY;
38 static final double NaNd = Double.NaN;
39
40
41
42
43
44
45
46 static long [] pythagoreanTriple(int m, int n) {
47 long M = m;
48 long N = n;
49 long result[] = new long[3];
50
51
52 result[0] = Math.abs(M*M - N*N);
53 result[1] = Math.abs(2*M*N);
54 result[2] = Math.abs(M*M + N*N);
55
56 return result;
57 }
58
59 static int testHypot() {
60 int failures = 0;
61
62 double [][] testCases = {
63
64 {infinityD, infinityD, infinityD},
65 {infinityD, 0.0, infinityD},
66 {infinityD, 1.0, infinityD},
67 {infinityD, NaNd, infinityD},
68 {NaNd, NaNd, NaNd},
69 {0.0, NaNd, NaNd},
70 {1.0, NaNd, NaNd},
71 {Double.longBitsToDouble(0x7FF0000000000001L), 1.0, NaNd},
72 {Double.longBitsToDouble(0xFFF0000000000001L), 1.0, NaNd},
73 {Double.longBitsToDouble(0x7FF8555555555555L), 1.0, NaNd},
74 {Double.longBitsToDouble(0xFFF8555555555555L), 1.0, NaNd},
75 {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), 1.0, NaNd},
76 {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), 1.0, NaNd},
77 {Double.longBitsToDouble(0x7FFDeadBeef00000L), 1.0, NaNd},
78 {Double.longBitsToDouble(0xFFFDeadBeef00000L), 1.0, NaNd},
79 {Double.longBitsToDouble(0x7FFCafeBabe00000L), 1.0, NaNd},
80 {Double.longBitsToDouble(0xFFFCafeBabe00000L), 1.0, NaNd},
81 };
82
83 for(int i = 0; i < testCases.length; i++) {
84 failures += testHypotCase(testCases[i][0], testCases[i][1],
85 testCases[i][2]);
86 }
87
88
89
90 for(int i = DoubleConsts.MIN_SUB_EXPONENT;
91 i <= DoubleConsts.MAX_EXPONENT;
92 i++) {
93 double input = FpUtils.scalb(2, i);
94 failures += testHypotCase(input, 0.0, input);
95 }
96
97
98
99
100
101 for(int m = 1; m < 10; m++) {
102 for(int n = m+1; n < 11; n++) {
103 long [] result = pythagoreanTriple(m, n);
104 failures += testHypotCase(result[0], result[1], result[2]);
105 }
106 }
107
108
109 for(int m = 100000; m < 100100; m++) {
110 for(int n = m+100000; n < 200200; n++) {
111 long [] result = pythagoreanTriple(m, n);
112 failures += testHypotCase(result[0], result[1], result[2]);
113 }
114 }
115
116
117
118
119
120
121
122
123
124
125 java.util.Random rand = new java.util.Random();
126 for(int i = 0; i < 1000; i++) {
127 double d = rand.nextDouble();
128
129 d = FpUtils.scalb(d, DoubleConsts.MAX_EXPONENT
130 -15 - FpUtils.ilogb(d));
131 for(int j = 0; j <= 13; j += 1) {
132 failures += testHypotCase(3*d, 4*d, 5*d, 2.5);
133 d *= 2.0;
134 }
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
149 {
150 double pcNeighbors[] = new double[5];
151 double pcNeighborsHypot[] = new double[5];
152 double pcNeighborsStrictHypot[] = new double[5];
153
154
155 for(int i = -18; i <= 18; i++) {
156 double pc = FpUtils.scalb(1.0, i);
157
158 pcNeighbors[2] = pc;
159 pcNeighbors[1] = FpUtils.nextDown(pc);
160 pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]);
161 pcNeighbors[3] = FpUtils.nextUp(pc);
162 pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]);
163
164 for(int j = 0; j < pcNeighbors.length; j++) {
165 pcNeighborsHypot[j] = Math.hypot(2.0, pcNeighbors[j]);
166 pcNeighborsStrictHypot[j] = StrictMath.hypot(2.0, pcNeighbors[j]);
167 }
168
169 for(int j = 0; j < pcNeighborsHypot.length-1; j++) {
170 if(pcNeighborsHypot[j] > pcNeighborsHypot[j+1] ) {
171 failures++;
172 System.err.println("Monotonicity failure for Math.hypot on " +
173 pcNeighbors[j] + " and " +
174 pcNeighbors[j+1] + "\n\treturned " +
175 pcNeighborsHypot[j] + " and " +
176 pcNeighborsHypot[j+1] );
177 }
178
179 if(pcNeighborsStrictHypot[j] > pcNeighborsStrictHypot[j+1] ) {
180 failures++;
181 System.err.println("Monotonicity failure for StrictMath.hypot on " +
182 pcNeighbors[j] + " and " +
183 pcNeighbors[j+1] + "\n\treturned " +
184 pcNeighborsStrictHypot[j] + " and " +
185 pcNeighborsStrictHypot[j+1] );
186 }
187
188
189 }
190
191 }
192 }
193
194
195 return failures;
196 }
197
198 static int testHypotCase(double input1, double input2, double expected) {
199 return testHypotCase(input1,input2, expected, 1);
200 }
201
202 static int testHypotCase(double input1, double input2, double expected,
203 double ulps) {
204 int failures = 0;
205 if (expected < 0.0) {
206 throw new AssertionError("Result of hypot must be greater than " +
207 "or equal to zero");
208 }
209
210
211
212
213
214 for(int i = -1; i <= 1; i+=2) {
215 for(int j = -1; j <= 1; j+=2) {
216 double x = i * input1;
217 double y = j * input2;
218 failures += Tests.testUlpDiff("Math.hypot", x, y,
219 Math.hypot(x, y), expected, ulps);
220 failures += Tests.testUlpDiff("Math.hypot", y, x,
221 Math.hypot(y, x ), expected, ulps);
222
223 failures += Tests.testUlpDiff("StrictMath.hypot", x, y,
224 StrictMath.hypot(x, y), expected, ulps);
225 failures += Tests.testUlpDiff("StrictMath.hypot", y, x,
226 StrictMath.hypot(y, x), expected, ulps);
227 }
228 }
229
230 return failures;
231 }
232
233 public static void main(String argv[]) {
234 int failures = 0;
235
236 failures += testHypot();
237
238 if (failures > 0) {
239 System.err.println("Testing the hypot incurred "
240 + failures + " failures.");
241 throw new RuntimeException();
242 }
243 }
244
245 }